package other.her.system.erp;

import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.ScheduleJob;
import com.rkhd.platform.sdk.data.model.SalesOutboundOrder__c;
import com.rkhd.platform.sdk.data.model.SyncConfig__c;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.param.ScheduleJobParam;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.her.system.client.ErpUtils;
import other.her.system.utils.HCXObjectService;
import other.her.system.utils.ResultVo;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 同步销售出库
 * @Author 黎炎松
 * 2024-10-15 16:01
 */
public class SyncSaleOut extends SyncSuper implements ScheduleJob, FutureTask {
    private static final Logger LOGGER = LoggerFactory.getLogger();
    private static final String LOGGER_MSG = "同步销售出库数据到CRM ==> ";

    /**
     * 计划作业触发
     * @param scheduleJobParam
     */
    @Override
    public void execute(ScheduleJobParam scheduleJobParam) {
        LOGGER.info(LOGGER_MSG + "触发计划作业");
        try {
            String messageId = FutureTaskService.instance().addFutureTask(getClass(), "2");
            LOGGER.info(LOGGER_MSG + "异步ID:" + messageId);
        } catch (Exception e) {
            LOGGER.error(LOGGER_MSG + " ----- 发生异常：" + e.getMessage());
        }
    }

    /**
     * 异步执行
     * @param type
     * @throws ScriptBusinessException
     */
    @Override
    public void execute(String type) {
        LOGGER.info(LOGGER_MSG + "触发异步同步");
        // 执行同步
        startSyncData(Integer.parseInt(type));

        // 同步其他出库
        SyncOtherOut syncOtherOut = new SyncOtherOut();
        syncOtherOut.startSyncData(2);
    }

    public static void main(String[] args)  {
        SyncSaleOut syncSaleOut = new SyncSaleOut();
        HCXObjectService.isLocal = true;
        //syncSaleOut.startSyncData(1);

        //syncSaleOut.queryUnLikeData();

        syncSaleOut.delRepeatData();
    }

    /**
     * 删除重复的数据
     */
    public void delRepeatData() {
        try {
            String sql = "select EntryID__c from salesOutboundOrder__c where zhangtao__c = 1 group by EntryID__c having count(EntryID__c) > 1 ";
            String entryIDs = XoqlService.instance().query(sql).getRecords().stream().map(v -> v.getString("EntryID__c")).collect(Collectors.joining(","));
            System.out.println("entryIDs = " + entryIDs);

            List<Long> crmRepeatIds = new ArrayList<>(); // 系统中重复的id
            sql = String.format("select id,EntryID__c from salesOutboundOrder__c where zhangtao__c = 1 and EntryID__c in (%s)", entryIDs);
            List<JSONObject> records = XoqlService.instance().query(sql).getRecords();
            records.stream().collect(Collectors.toMap(e -> e.getString("EntryID__c"), e1 -> e1.getLong("id"), (e, e1) -> {
                crmRepeatIds.add(e1);
                return e;
            }));
            System.out.println("crmRepeatIds = " + crmRepeatIds.size());

            List<SalesOutboundOrder__c> repeatDelList = crmRepeatIds.stream().map(v -> {
                SalesOutboundOrder__c salesOutboundOrder = new SalesOutboundOrder__c();
                salesOutboundOrder.setId(v);
                return salesOutboundOrder;
            }).collect(Collectors.toList());
            LOGGER.info(LOGGER_MSG + "需要删除的数据:" + repeatDelList.size());
            HCXObjectService.deleteBatch(repeatDelList);
        } catch (ApiEntityServiceException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查找CRM-ERP 不同的数据
     */
    public void queryUnLikeData(){
        String sql = "select t0.FInterID,t0.FEntryID from ICStockBillEntry t0 left join ICStockBill t1 on t0.FInterID = t1.FInterID where FTranType = 21 and t1.FStatus != 0 and t1.Fdate = '2024-06-05'";
        List<JSONObject> query = ErpUtils.query(sql, "http://47.92.3.51:8089/huierrui/her");
        List<String> collect = query.stream().map(v -> v.getString("FInterID") + v.getString("FEntryID")).collect(Collectors.toList());
        System.out.println("query = " + collect.size());

        sql = "select EntryID__c from salesOutboundOrder__c where zhangtao__c = 1 and Fdate__c = 1717516800000 ";
        List<JSONObject> records = null;
        try {
            records = XoqlService.instance().query(sql).getRecords();
        } catch (ApiEntityServiceException e) {
            throw new RuntimeException(e);
        }
        System.out.println("records = " + records.size());

        Set<String> idSet = new HashSet<>();
        for (JSONObject record : records) {
            String entryID = record.getString("EntryID__c");
            if (idSet.contains(entryID)) {
                System.out.println("entryID = " + entryID);
            }
            idSet.add(entryID);
        }

        List<JSONObject> entryID__c = records.stream().filter(v -> !collect.contains(v.getString("EntryID__c"))).collect(Collectors.toList());
        System.out.println("entryID__c = " + entryID__c);
    }

    /**
     * 开始同步不同账套ERP有变化的数据
     * @param type 1:首次批量处理 2：后续增量处理
     */
    public void startSyncData(int type) {
        // 获取同步配置里面的开始和结束时间
        SyncConfig__c syncConfig = getSyncConfig("ERP_XXCK");

        // 处理不同账套的数据
        for (Map<String, String> account : accountList) {
            if (type == 1) {
                initDataByAccount(account, syncConfig);
            } else {
                dealErpChangeDataByAccount(account);
            }
        }

        // 更新上次同步时间
        upSyncConfig(syncConfig);
    }



    /**
     * 增量处理ERP变化的数据
     */
    public void dealErpChangeDataByAccount(Map<String, String> account) {
        try {
            LOGGER.info(LOGGER_MSG + "开始处理新增、修改的数据: " + account.get("accountName"));

            // 查询ERP当前模块有变化的数据
            Map<String, String> module = moduleMap.get("xsck");
            Map<String, String> idMap = getErpChangeData(module, account);
            if (idMap == null) {
                LOGGER.info("没有需要处理的数据");
                return;
            }

            // 新增、修改CRM数据
            String addUpIds = idMap.get("addUpIds");
            if (StringUtils.isNotBlank(addUpIds)) {
                String filterStr = String.format(" and t0.%s in (%s) ", module.get("idKey"), addUpIds);
                LOGGER.info(LOGGER_MSG + "filterStr: " + filterStr);
                ResultVo resultVo = syncErpSaleOut(account, filterStr);
                if (resultVo.getCode() != 200) {
                    LOGGER.error(LOGGER_MSG + "处理新增、修改数据异常");
                    return;
                }
            }

            // 删除CRM数据 (根据账套 + 主表id删除数据)
            delCrmTableData("salesOutboundOrder__c", account.get("accountVal"), idMap.get("delIds"));

            // 需要把ERP处理完的记录表数据删除
            delErpRecordTable(idMap.get("erpTableIds"), account);

        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error(account.get("accountName") + ": 增量处理ERP变化的数据 => " + e.getMessage());
        }
    }

    /**
     * 首次初始化数据 （没有创建时间、修改时间，使用自动排序进行分页查询）
     *
     * @param account
     * @param syncConfig
     */
    public void initDataByAccount(Map<String, String> account, SyncConfig__c syncConfig) {
        LOGGER.info(LOGGER_MSG + "开始初始化数据: " + account.get("accountName"));

        // 基础查询
        String baseSql = String.format("select ROW_NUMBER() over(order by FInterID) as num,FInterID from ICStockBill " +
                " where FTranType = 21 and FStatus != 0 and FDate between '%s' and '%s'", syncConfig.getAttribute("startTime"), syncConfig.getAttribute("endTime"));

        // 获取当前查询的总数量
        String countSql = String.format("select count(*) as count from (%s) t", baseSql);
        JSONObject countObj = ErpUtils.queryOne(countSql, account.get("domain"));
        if (countObj == null) {
            LOGGER.error(LOGGER_MSG + "获取总数异常");
            return;
        }

        // 总数
        Integer tableCount = countObj.getInteger("count");
        LOGGER.info(LOGGER_MSG + "tableCount: " + tableCount);
        if (tableCount > 5000) {
            tableCount = 5000;
        }

        // 根据分页获取数据进行同步
        int startCount = 0;
        while (startCount < tableCount) {
            String filterSql = String.format(" and t0.FInterID in ( select FInterID from (%s) t where t.num between %d and %d ) ", baseSql, startCount, startCount += 100);
            LOGGER.info(LOGGER_MSG + "filterSql: " + filterSql);
            syncErpSaleOut(account, filterSql);
        }

        LOGGER.info(LOGGER_MSG + "初始化数据结束: " + account.get("accountName"));
    }


    /**
     * 同步erp销售出库 FTranType 单据类型
     * @return
     */
    public ResultVo syncErpSaleOut(Map<String, String> account, String filterStr) {
        try {
            LOGGER.info(LOGGER_MSG + "开始同步");
            int accountVal = Integer.parseInt(account.get("accountVal")); // CRM所属账套的值
            String speciaField = account.get("speciaField");

            // 查询数据
            String erpSql = "select t0.FInterID,t0.FEntryID,t1.FSupplyID,t1.Fdate,t1.FStatus,t1.FBillNo,t1.FExplanation,t1.FEmpID,\n" +
                    "t0.FSourceBillNo,t0.FOrderBillNo,t0.FItemID,t0.FQtyMust,t0.FAuxPrice,t0.FAmount,t0.FConsignPrice,t0.FDiscountRate,\n" +
                    "t0.FConsignAmount,t0.FQtyInvoiceBase,t0.FNote,t0.FBatchNo,t0.FKFDate,t0.FKFPeriod,t0.FPeriodDate,t0.FTaxRate,\n" +
                    "t0.FTaxAmount,t0.FFetchDate,t0.Fauxqty,sub.FName as saleStyleName,\n" +
                    "org.FName as orgName,org.FNumber as orgNumber,emp.FName empName,cp.FNumber as cpNumber " + speciaField +
                    "from ICStockBillEntry t0 \n" +
                    "left join ICStockBill t1 on t0.FInterID = t1.FInterID \n" +
                    "left join t_Organization org on t1.FSupplyID = org.FItemID \n" +
                    "left join t_Base_Emp emp on t1.FEmpID = emp.FItemID \n" +
                    "left join t_ICItemCore cp on t0.FItemID = cp.FItemID \n" +
                    "left join t_SubMessage sub on t1.FSaleStyle = sub.FinterID \n" +
                    "where t1.FTranType = 21 ";
            // 增加过滤条件
            if (StringUtils.isNotBlank(filterStr)) {
                erpSql += filterStr;
            }
            erpSql += " ORDER BY t0.FInterID ";

            List<JSONObject> erpDataList = ErpUtils.query(erpSql, account.get("domain"));
            LOGGER.info(LOGGER_MSG + "erpDataList: " + erpDataList.size());
            if (erpDataList == null || erpDataList.size() <= 0) {
                LOGGER.info(LOGGER_MSG + "查询异常或者没有需要同步的数据");
                return ResultVo.success();
            }

            // 根据ERP数据id查询CRM系统存在的数据 (明细标识：主表id + 明细序号)
            List<Long> crmRepeatIds =new ArrayList<>(); // 系统中重复的id
            String filterVals = erpDataList.stream().map(v -> "'" + v.getString("FInterID") + "'").collect(Collectors.joining(","));
            String sql = String.format("select id,ERPID__c,EntryID__c from salesOutboundOrder__c where zhangtao__c = %d and ERPID__c in (%s)", accountVal, filterVals);
            List<JSONObject> crmDataList = XoqlService.instance().query(sql).getRecords();
            Map<String, Long> crmDataMap = crmDataList.stream().collect(Collectors.toMap(e -> e.getString("EntryID__c"), e1 -> e1.getLong("id"), (e, e1) -> {
                crmRepeatIds.add(e1);
                return e;
            }));
            LOGGER.info(LOGGER_MSG + "crmDataMap: " + crmDataMap.size());

            // 获取CRM客户、用户、产品数据
            Map<String, Long> crmUserMap = getCrmDataMap("user", "empName", accountVal, erpDataList);
            Map<String, Long> crmAccountMap = getCrmDataMap("account", "orgNumber", accountVal, erpDataList);
            Map<String, Long> crmProductMap = getCrmDataMap("product", "cpNumber", accountVal, erpDataList);

            // 新增、修改数据
            HashSet<String> hasDealIds = new HashSet<>();
            List<SalesOutboundOrder__c> crmAddList = new ArrayList<>();
            List<SalesOutboundOrder__c> crmUpList = new ArrayList<>();
            for (JSONObject erpData : erpDataList) {
                // 唯一标识
                String entryId = erpData.getString("FInterID") + erpData.getString("FEntryID");

                SalesOutboundOrder__c salesOut = new SalesOutboundOrder__c();
                salesOut.setERPID__c(erpData.getString("FInterID")); // 主表id

                salesOut.setAccountName__c(crmAccountMap.get(erpData.getString("orgNumber"))); // 客户名称(关联关系-客户)
                salesOut.setFdate__c(getDateVal(erpData.getString("Fdate"))); // 日期
                salesOut.setFStatus__c(!Objects.equals(erpData.getInteger("FStatus"), 0) ? "Y" : "N"); // 审批标识 FStatus 不等于0都是Y
                salesOut.setName(erpData.getString("FBillNo")); // ERP出库单单据编号
                salesOut.setFExplanation__c(erpData.getString("FExplanation")); // 摘要

                // 业务员(关联关系-用户)
                Long ownerId = crmUserMap.get(erpData.getString("empName"));
                if (ownerId != null) {
                    salesOut.setOwnerId(ownerId);
                }
                salesOut.setFSaleStyle__c(erpData.getString("saleStyleName")); // 销售方式
                salesOut.setFSourceBillNo__c(erpData.getString("FSourceBillNo")); // 源单单号
                salesOut.setFOrderBillNo__c(erpData.getString("FOrderBillNo")); // 订单单号
                salesOut.setProductName__c(crmProductMap.get(erpData.getString("cpNumber"))); // 产品编码（关联关系-产品）
                salesOut.setFQtyMust__c(erpData.getDouble("FQtyMust")); // 应发数量
                salesOut.setFauxqtyf__c(erpData.getDouble("Fauxqty")); // 实发数量
                salesOut.setFAuxPrice__c(erpData.getDouble("FAuxPrice")); // 单位成本
                salesOut.setFAmount__c(erpData.getDouble("FAmount")); // 成本
                salesOut.setFConsignPrice__c(erpData.getDouble("FConsignPrice")); // 销售单价
                salesOut.setFDiscountRate__c(bgDivide(erpData.getDouble("FDiscountRate"), 100)); // 折扣率
                salesOut.setFEntrySelfB0167__c(erpData.getDouble("discountPrice")); // 折后单价
                salesOut.setFConsignAmount__c(erpData.getDouble("FConsignAmount")); // 销售金额
                salesOut.setFQtyInvoiceBase__c(erpData.getDouble("FQtyInvoiceBase")); // 开票数量
                salesOut.setFNote__c(erpData.getString("FNote")); // 备注
                salesOut.setFBatchNo__c(erpData.getString("FBatchNo")); // 批号
                salesOut.setFKFDate__c(getDateVal(erpData.getString("FKFDate"))); // 生产/采购日期
                salesOut.setFKFPeriod__c(erpData.getString("FKFPeriod")); // 保质期（天）
                salesOut.setFPeriodDate__c(getDateVal(erpData.getString("FPeriodDate"))); // 有效期至
                salesOut.setFTaxRate__c(erpData.getDouble("FTaxRate")); // 税率
                salesOut.setFTaxAmount__c(erpData.getDouble("FTaxAmount")); // 税额
                salesOut.setFFetchDate__c(getDateVal(erpData.getString("FFetchDate"))); // 交货日期

                if (crmDataMap.containsKey(entryId)) {
                    // 编辑
                    salesOut.setId(crmDataMap.get(entryId));
                    crmUpList.add(salesOut);
                } else {
                    // 新增
                    salesOut.setEntityType(3505056499194460L); // 业务类型
                    salesOut.setZhangtao__c(accountVal); // 所属账套
                    salesOut.setEntryID__c(entryId); // 明细id
                    crmAddList.add(salesOut);
                }

                // 批量新增、更新
                if (crmAddList.size() > 50) {
                    HCXObjectService.insertBatch(crmAddList);
                    crmAddList.clear();
                }
                if (crmUpList.size() > 50) {
                    HCXObjectService.updateBatch(crmUpList);
                    crmUpList.clear();
                }

                // 记录已经处理的id
                hasDealIds.add(entryId);
            }

            // 批量保存产品数据
            HCXObjectService.insertBatch(crmAddList);
            HCXObjectService.updateBatch(crmUpList);

            // 判断需要删除的数据（需要考虑ERP删除明细的情况）
            List<SalesOutboundOrder__c> crmDelList = crmDataList.stream().filter(v -> !hasDealIds.contains(v.getString("EntryID__c"))).map(v -> {
                SalesOutboundOrder__c salesOutboundOrder = new SalesOutboundOrder__c();
                salesOutboundOrder.setId(v.getLong("id"));
                return salesOutboundOrder;
            }).collect(Collectors.toList());
            // 删除重复的数据
            List<SalesOutboundOrder__c> repeatDelList = crmRepeatIds.stream().map(v -> {
                SalesOutboundOrder__c salesOutboundOrder = new SalesOutboundOrder__c();
                salesOutboundOrder.setId(v);
                return salesOutboundOrder;
            }).collect(Collectors.toList());
            crmDelList.addAll(repeatDelList);
            LOGGER.info(LOGGER_MSG + "需要删除的数据:" + crmDelList);
            HCXObjectService.deleteBatch(crmDelList);

            LOGGER.info(LOGGER_MSG + "同步结束");
            return ResultVo.success();
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("同步产品异常:" + e.getMessage());
            return ResultVo.error("同步产品异常:" + e.getMessage());
        }
    }


}
